package cn.sixmillions.ps.common.base;

import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;

import java.io.Serial;
import java.io.Serializable;
import java.time.Instant;
import java.util.Optional;

/**
 * 统一返回结果封装
 *
 * @author six
 * @since 2022-09-01
 */
@Data
@EqualsAndHashCode
@SuppressWarnings("unused")
public class R<T> implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 状态码
     */
    private int code;

    /**
     * 返回数据
     */
    private T data;

    /**
     * 返回消息
     */
    private String message;

    /**
     * 返回时间戳
     */
    private Long time;

    /**
     * 错误代码
     */
    private String errorCode;

    public R() {
    }

    /**
     * @param code    状态码
     * @param data    返回数据
     * @param message 返回消息
     */
    private R(int code, T data, String message) {
        this(code, data, message, "");
    }

    private R(int code, T data, String message, String errorCode) {
        this.code = code;
        this.data = data;
        this.message = message;
        this.errorCode = errorCode;
        this.time = Instant.now().getEpochSecond();
    }

    public static <T> R<T> data(T data) {
        return new R<>(HttpStatus.OK.value(), data, "SUCCESS");
    }

    public static <T> R<T> success() {
        return success("SUCCESS");
    }

    /**
     * 成功返回：无返回数据
     *
     * @param msg 返回消息
     * @param <T> 返回结果泛型
     * @return 统一封装的返回结果
     */
    public static <T> R<T> success(String msg) {
        return new R<>(HttpStatus.OK.value(), null, msg);
    }

    public static <T> R<T> fail() {
        return fail("FAILURE");
    }


    /**
     * 失败返回
     *
     * @param msg 返回消息
     * @param <T> 返回结果泛型
     * @return 统一封装的返回结果
     */
    public static <T> R<T> fail(String msg) {
        return new R<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), null, msg);
    }

    /**
     * 失败返回
     *
     * @param errorCode 错误代码
     * @param msg       返回消息
     * @param <T>       返回结果泛型
     * @return 统一封装的返回结果
     */
    public static <T> R<T> fail(String errorCode, String msg) {
        return new R<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), null, msg, errorCode);
    }


    /**
     * 成功
     *
     * @param result R
     * @return 是否成功
     */
    public static boolean isSuccess(@Nullable R<?> result) {
        return Optional.ofNullable(result).map(x -> HttpStatus.OK.value() == x.code).orElse(Boolean.FALSE);
    }

    /**
     * 不成功
     *
     * @param result R
     * @return 是否失败
     */
    public static boolean isNotSuccess(@Nullable R<?> result) {
        return !isSuccess(result);
    }
}
